概述
在 Android 中可以把媒体通知显示在 QS 上,这个特性可以通过下面的开关来配置:
1 | packages/SystemUI/src/com/android/systemui/util/Utils.java |
如果不显示在QS上,那么就显示在通知中心里面。
在 Android S上面分别有四个位置可以承载媒体控制器,分别时QQS、QS和锁屏,另外还有个动画切换的场景,这四个位置动态添加 MediaScrollView 来实现切换场景时媒体控制器的位置的变换。
如图:
媒体控制器容器布局在 R.layout.media_carousel,媒体控制器布局是 R.layout.media_view。
1 | UniqueObjectHostView |
相关的类:
- MediaHierarchyManager 管理媒体控制器在不同host view之间的切换已经它们之间的切换动画
- MediaHost
- UniqueObjectHostView 承载媒体控制器的容器,它是 MediaHost 的一个变量,一个 MediaHost 对应一个 UniqueObjectHostView
- MediaCarouselController
- MediaControlPanel 控制多媒体播放
在 MediaHierarchyManager 中定义了媒体控制器的四个位置场景。
1 | // MediaHierarchyManager.kt |
定义了一个数组 mediaHosts 来保存
1 | private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_LOCKSCREEN + 1) |
初始化
三个场景分别定义了三个 MediaHost,并且实例化了三个 UniqueObjectHostView View,这三个View是在 SystemUI初始化时就创建的,然后添加到各个场景的UI中去,不管此时有没有媒体创建的需求。
锁屏初始化:
1 | KeyguardMediaController.kt |
QS初始化:
1 | QSPanelController.java |
QQS 初始化:
1 | QuickQSPanelController.java |
MediaHost 初始化:
1 | MediaHost.init() |
添加流程
1 | MediaDataCombineLatest.onMediaDeviceChanged() |
1 | MediaHierarchyManager.updateDesiredLocation() |
可见性更新流程
MediaHost 提供了 addVisibilityChangeListener() 方法,当媒体通知的可见性发生变化时会通知监听者响应的变化。
在 KeyguardMediaController 、 MediaHierarchyManager 和 QSPanelControllerBase 都创建了监听。QSPanelControllerBase 收到监听后会把变化通过 mMediaVisibilityChangedListener 通知到 QSFragment (setCollapsedMediaVisibilityChangedListener()),在通知到 NotificationPanelViewController (setMediaVisibilityChangedListener())。
切换动画流程
切换动画是在 ViewGroupOverlay 上面做的,根据手势的移动位置来计算出 mediaFrame 的显示区域,然后通过不断更新显示区域来实现移动的动画效果。
媒体控制器内部的联动动画是通过 TransitionLayout 来实现的。
1 | NotificationPanelViewController.updateQsExpansion() |
1 | PlayerViewHolder.kt |
方法详解
1 | //MediaHierarchyManager.kt |
1 | private fun getHost(@MediaLocation location: Int): MediaHost? { |
1 | private fun updateViewVisibility() { |
1 | private fun getQSTransformationProgress(): Float { |
1 | // 以LOCATION_QQS的可见性来判断是否有 ActiveMedia |